<template>
  <view class="container">
    <!-- 1. 相机页面 (已重构) -->
    <view v-if="pageState === 'camera'" class="camera-container">
      <!-- 1.1 相机预览区域 -->
      <view class="camera-wrapper">
        <!-- 移除了 `v-if="!singlePhotoPath"` 判断，因为在 'camera' 状态下它永远为 true -->
        <canvas v-show="showCamera" ref="canvasElement" class="camera-canvas"></canvas>
        <view class="camera-prompt">
          <text class="prompt-text">{{ currentTextTips }}</text>
        </view>
        <image class="guide-image" :src="currentOverlay" />

        <view v-if="canSkip" class="skip-prompt-box" @click="skipOptionalPhotos">
          <text>如果不想拍摄侧脸病症，请</text>
          <text class="skip-highlight">跳过</text>
        </view>
      </view>

      <!-- 1.2 底部控制区域 -->
      <view class="bottom-controls">
        <view v-if="cameraSource === 'acupoint'" class="part-selector">
          <scroll-view scroll-x="true" class="scroll-view" show-scrollbar="false">
            <view
              v-for="(part, index) in bodyParts"
              :key="part.id"
              class="part-item"
              :class="{ active: active_id === part.id }"
              @click="selectPart(index, part.id)"
              >{{ part.body_name }}</view
            >
          </scroll-view>
        </view>
        <view class="action-buttons">
          <view class="button-wrapper">
            <image src="/static/icons/posture.png" class="icon-placeholder" mode="aspectFit"></image>
            <text class="btn-text">{{ t('zhen.posture') }}</text>
          </view>
          <view class="shutter-button-wrapper" @click="takePhoto" :class="{ disabled: !showCamera }">
            <view class="shutter-button"></view>
          </view>
          <view class="button-wrapper" @click="switchCamera">
            <image src="/static/icons/phone.png" class="icon-placeholder" mode="aspectFit"></image>
            <text class="btn-text">{{ t('zhen.switch') }}</text>
          </view>
        </view>
      </view>
    </view>

    <!-- [新增] 2. 单张照片确认页面 -->
    <view v-else-if="pageState === 'singleConfirm'" class="camera-container">
      <!-- 2.1 照片预览区域 -->
      <view class="camera-wrapper">
        <image :src="singlePhotoPath" class="preview-image" mode="heightFix" />
      </view>
      <!-- 2.2 底部控制区域 -->
      <view class="bottom-controls">
        <view class="confirm-actions">
          <view class="button-wrapper" @click="retake"
            ><text class="btn-text">{{ t('zhen.retake') }}</text></view
          >
          <view class="button-wrapper" @click="confirm"
            ><text class="btn-text primary">{{ t('zhen.confirm') }}</text></view
          >
        </view>
      </view>
    </view>

    <!-- 3. 多照片确认页面 -->
    <view v-else-if="pageState === 'multiConfirm'" class="confirm-page-container">
      <view class="confirm-page-header">
        <text class="header-title">{{ pageTitle }}</text>
      </view>
      <scroll-view scroll-y class="confirm-scroll-view">
        <view class="scroll-content-wrapper">
          <view v-for="(photo, index) in capturedPhotos" :key="index">
            <div v-if="photo.path" class="photo-item">
              <text class="photo-label">{{ currentWorkflow.steps[index].label }}</text>
              <image :src="photo.path" class="photo-preview" mode="aspectFill"></image>
            </div>
          </view>
        </view>
      </scroll-view>
      <view class="confirm-page-footer">
        <button class="footer-btn retake-btn" :disabled="isPolling" @click="retakeMultiPhotos">
          {{ $t('zhen.retake_multi') }}
        </button>
        <button class="footer-btn confirm-btn" :loading="isPolling" :disabled="isPolling" @click="confirmMultiPhotos">
          {{ isPolling ? $t('zhen.analyzing') : $t('zhen.confirm_multi') }}
        </button>
      </view>
    </view>
    <view v-else-if="pageState === 'switch'"></view>
    <!-- 4. 问卷调查页面 -->
    <view v-else-if="pageState === 'questionnaire'" class="questionnaire-page">
      <view class="questionnaire-header">
        <view class="header-text">{{ $t('zhen.questionnaire_tip1') }}</view>
        <view class="header-text">{{ $t('zhen.questionnaire_tip2') }}</view>
      </view>

      <scroll-view scroll-y class="questionnaire-scroll">
        <view class="question-list" :class="{ answering: isAnswering }">
          <view v-for="question in questionnaireData.questions" :key="question.subjectId" class="question-card">
            <view class="question-title-wrapper">
              <text class="question-title">{{ question.subjectTitle }}</text>
            </view>
            <view class="answer-options">
              <template v-if="question.subjectType === 0">
                <input
                  v-model="answers[question.subjectId]"
                  class="age-input"
                  type="number"
                  :placeholder="question.answer[0].answerTitle"
                  @blur="handleAgeInput(question.subjectId)" />
              </template>

              <template v-if="question.subjectType === 1">
                <view
                  v-for="option in question.answer"
                  :key="option.answerCode"
                  class="answer-btn"
                  :class="{ active: answers[question.subjectId] === option.answerCode }"
                  @click="selectAnswer(question.subjectId, option.answerCode)">
                  {{ option.answerTitle }}
                </view>
              </template>
            </view>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 5. 结果展示页面 -->
    <view v-else>
      <tongue-results-page v-if="cameraSource === 'tongue'" :result-data="analysisResult" @restart="restart" />
      <face-results-page v-if="cameraSource === 'face'" :result-data="analysisResult" @restart="restart" />
      <results-page
        v-else
        :photo-path="analysisResult.picUrl"
        :acupoint-list="analysisResult.acupointList"
        :link-to="analysisResult.linkTo"
        @restart="restart" />
    </view>
  </view>
</template>

<script>
  import ResultsPage from './ResultsPage.vue'
  import TongueResultsPage from './TongueResultsPage.vue'
  import FaceResultsPage from './FaceResultsPage.vue'
  import { upload } from '@/utils/request.js'
  import { useI18n } from 'vue-i18n'
  import {
    getpartlist,
    createAcupoint,
    checkStatus,
    getResult,
    createTonguet,
    checkTongueStatus,
    getTongueResult,
    createFaceDiagnosis,
    answerQuestion,
    getFinalFaceResult
  } from '@/api/acupoint.js'
  import { useUserStore } from '@/store/user.js'
  import { uni } from '@dcloudio/uni-h5'

  export default {
    components: {
      ResultsPage,
      TongueResultsPage,
      FaceResultsPage
    },
    data() {
      return {
        // --- 页面状态管理 ---
        // [MODIFIED] 新增 'singleConfirm' 状态
        pageState: 'camera', // 'camera', 'singleConfirm', 'multiConfirm', 'questionnaire', 'results',switch
        cameraSource: 'acupoint', // 'acupoint', 'tongue', 'face'

        // --- 相机核心 ---
        showCamera: false,
        isFrontCamera: false,
        stream: null,
        videoElement: null,
        canvasContext: null,
        animationFrameId: null,
        screenWidth: 0,
        screenHeight: 0,

        // --- 单张照片工作流 (穴位识别) ---
        singlePhotoPath: '', // 存储单张照片的临时路径
        bodyParts: [],
        activePartIndex: 0,
        active_id: 0,

        // --- 问卷相关数据 ---
        questionnaireData: {
          faceId: null,
          id: null,
          questions: []
        },
        answers: {},
        isAnswering: false,

        // --- 多步骤拍照工作流 ---
        // 只保留类型key，具体内容用computed
        photoWorkflowType: 'tongue', // 或 'face'，实际用 this.cameraSource
        currentStepIndex: 0,
        capturedPhotos: [],

        // --- 结果与轮询 ---
        analysisResult: { picUrl: '', acupointList: [], linkTo: {} },
        appoint_no: null,
        pollCount: 0,
        maxPollCount: 10,
        interval: 1000,
        pollTimer: null,
        isPolling: false
      }
    },
    setup() {
      const { t } = useI18n()
      return { t }
    },
    computed: {
      canSkip() {
        return this.cameraSource === 'face' && this.currentStepIndex > 0
      },
      isMultiStepFlow() {
        return this.cameraSource === 'tongue' || this.cameraSource === 'face'
      },
      workflowConfig() {
        // 用于多语言的动态配置
        if (this.cameraSource === 'tongue') {
          return {
            title: this.$t('zhen.workflow.tongue.title'),
            steps: [
              {
                label: this.$t('zhen.workflow.tongue.steps[0].label'),
                prompt: this.$t('zhen.workflow.tongue.steps[0].prompt'),
                overlay: '/static/overlays/01.png'
              },
              {
                label: this.$t('zhen.workflow.tongue.steps[1].label'),
                prompt: this.$t('zhen.workflow.tongue.steps[1].prompt'),
                overlay: '/static/overlays/tongue.png'
              }
            ]
          }
        } else if (this.cameraSource === 'face') {
          return {
            title: this.$t('zhen.workflow.face.title'),
            steps: [
              {
                label: this.$t('zhen.workflow.face.steps[0].label'),
                prompt: this.$t('zhen.workflow.face.steps[0].prompt'),
                overlay: '/static/overlays/face_01.png'
              },
              {
                label: this.$t('zhen.workflow.face.steps[1].label'),
                prompt: this.$t('zhen.workflow.face.steps[1].prompt'),
                overlay: '/static/overlays/face_02.png'
              },
              {
                label: this.$t('zhen.workflow.face.steps[2].label'),
                prompt: this.$t('zhen.workflow.face.steps[2].prompt'),
                overlay: '/static/overlays/face_02.png'
              }
            ]
          }
        }
        return {}
      },
      currentWorkflow() {
        return this.workflowConfig
      },
      currentStepConfig() {
        if (!this.isMultiStepFlow) return null
        return this.workflowConfig.steps[this.currentStepIndex]
      },
      pageTitle() {
        return this.isMultiStepFlow ? this.workflowConfig.title : this.$t('acupoint.title')
      },
      currentTextTips() {
        if (this.isMultiStepFlow) {
          return this.currentStepConfig?.prompt || ''
        }
        return this.bodyParts[this.activePartIndex]?.remark || this.$t('zhen.acupoint_photo_tip')
      },
      currentOverlay() {
        if (this.isMultiStepFlow) {
          return this.currentStepConfig?.overlay || ''
        }
        return this.bodyParts[this.activePartIndex]?.img_url || ''
      },
      userStore() {
        return useUserStore()
      },
      userInfo() {
        return this.userStore.userInfo
      }
    },
    onLoad(options) {
      if (options && options.source) {
        this.cameraSource = options.source
        // console.log('当前相机来源:', this.cameraSource)
      } else {
        // console.warn('未指定相机来源，将使用默认逻辑。')
      }
      this.initializeBasedOnSource()
      this.setNavTitle()
    },
    onReady() {
      if (this.pageState === 'camera') {
        this.initCamera()
        // new VConsole()
      }
      this.setNavTitle()
    },
    onUnload() {
      this.stopCamera()
    },
    watch: {
      '$i18n.locale'() {
        this.setNavTitle()
      }
    },
    methods: {
      setNavTitle() {
        let key = 'tongue.title'
        if (this.cameraSource === 'acupoint') key = 'acupoint.title'
        if (this.cameraSource === 'face') key = 'face.title'
        uni.setNavigationBarTitle({ title: this.$t(key) })
      },
      initializeBasedOnSource() {
        this.resetWorkflowState()
        if (this.cameraSource === 'acupoint') {
          this.getpartListData()
        }
      },
      resetWorkflowState() {
        this.currentStepIndex = 0
        this.capturedPhotos = []
        this.singlePhotoPath = ''
        this.questionnaireData = { faceId: null, id: null, questions: [] }
        this.answers = {}
        this.isAnswering = false
        this.isPolling = false
      },
      async getpartListData() {
        const res = await getpartlist()
        if (res.result && res.result.length > 0) {
          this.bodyParts = res.result
          this.active_id = res.result[0].id
        }
      },
      // ... (initCamera, startDrawing, getCanvasElement methods remain the same) ...
      async initCamera() {
        this.stopCamera()
        try {
          const rect = await new Promise(resolve => {
            uni
              .createSelectorQuery()
              .in(this)
              .select('.camera-wrapper')
              .boundingClientRect(data => {
                if (data) {
                  this.screenWidth = data.width
                  this.screenHeight = data.height
                } else {
                  this.screenWidth = window.innerWidth
                  this.screenHeight = window.innerHeight
                  console.warn('获取 .camera-wrapper 尺寸失败, 使用 window 尺寸作为备用。')
                }
                resolve(data)
              })
              .exec()
          })

          const canvas = await this.getCanvasElement()
          if (!canvas) return

          canvas.width = this.screenWidth
          canvas.height = this.screenHeight

          this.canvasContext = canvas.getContext('2d')
          this.videoElement = document.createElement('video')
          this.videoElement.setAttribute('playsinline', true)
          this.videoElement.muted = true
          this.videoElement.autoplay = true
          this.videoElement.style.display = 'none'
          document.body.appendChild(this.videoElement)
          this.stream = await navigator.mediaDevices.getUserMedia({
            video: { facingMode: this.isFrontCamera ? 'user' : 'environment' }
          })
          this.videoElement.srcObject = this.stream
          this.videoElement.onloadedmetadata = () => {
            this.videoElement.play()
            this.showCamera = true
            this.startDrawing()
          }
        } catch (error) {
          console.error('相机启动失败:', error)
          uni.showModal({
            title: this.$t('zhen.camera_error'),
            content: this.$t('zhen.camera_error_content'),
            showCancel: false
          })
        }
      },

      startDrawing() {
        if (!this.showCamera || !this.videoElement || !this.videoElement.videoWidth) {
          if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId)
          this.animationFrameId = null
          return
        }

        const ctx = this.canvasContext
        const canvasWidth = this.screenWidth
        const canvasHeight = this.screenHeight

        // 获取视频的原始尺寸
        const videoWidth = this.videoElement.videoWidth
        const videoHeight = this.videoElement.videoHeight

        // 计算视频和Canvas的宽高比
        const videoRatio = videoWidth / videoHeight
        const canvasRatio = canvasWidth / canvasHeight

        let drawWidth, drawHeight, offsetX, offsetY

        // 核心逻辑：计算如何绘制才能保持比例并填满Canvas
        if (videoRatio > canvasRatio) {
          // 视频比Canvas更宽：高度撑满，宽度裁剪
          drawHeight = canvasHeight
          drawWidth = drawHeight * videoRatio
          offsetX = (canvasWidth - drawWidth) / 2 // 水平居中
          offsetY = 0
        } else {
          // 视频比Canvas更高（或比例相同）：宽度撑满，高度裁剪
          drawWidth = canvasWidth
          drawHeight = drawWidth / videoRatio
          offsetX = 0
          offsetY = (canvasHeight - drawHeight) / 2 // 垂直居中
        }

        ctx.clearRect(0, 0, canvasWidth, canvasHeight)

        // 保存当前上下文状态
        ctx.save()

        if (this.isFrontCamera) {
          // 前置摄像头需要水平翻转
          ctx.translate(canvasWidth, 0)
          ctx.scale(-1, 1)
        }

        // 使用计算出的尺寸和偏移量进行绘制
        ctx.drawImage(this.videoElement, offsetX, offsetY, drawWidth, drawHeight)

        // 恢复到翻转前的状态
        ctx.restore()

        this.animationFrameId = requestAnimationFrame(this.startDrawing.bind(this))
      },
      getCanvasElement() {
        return new Promise(resolve => {
          uni
            .createSelectorQuery()
            .in(this)
            .select('.camera-canvas')
            .node(res => resolve(res ? res.node : null))
            .exec()
        })
      },
      async takePhoto() {
        // 1. 检查相机是否就绪
        if (!this.showCamera) {
          console.warn('Camera not ready, cannot take photo.')
          return
        }

        // 2. 获取用户当前正在预览的那个 Canvas 元素
        //    我们用 async/await 来确保能拿到元素
        const canvasElement = await this.getCanvasElement()
        if (!canvasElement) {
          console.error('Failed to get the main canvas element for taking a photo.')
          uni.showToast({ title: '拍照失败，请重试', icon: 'none' })
          return
        }

        // 3. 直接从这个可见的 Canvas 中导出图像数据
        //    这能保证捕获的图像与用户看到的预览完全一致
        const photoBase64 = canvasElement.toDataURL('image/jpeg', 0.9)

        // 4. 后续逻辑保持不变
        if (this.isMultiStepFlow) {
          // 多步骤流程
          this.capturedPhotos.push({ path: photoBase64 })
          this.currentStepIndex++
          if (this.currentStepIndex >= this.currentWorkflow.steps.length) {
            this.stopCamera()
            this.pageState = 'multiConfirm'
          } else {
            uni.showToast({
              title: this.$t('zhen.please_prepare', { label: this.currentStepConfig.label }),
              icon: 'none',
              duration: 1500
            })
          }
        } else {
          // 单张照片流程 (穴位识别)
          this.singlePhotoPath = photoBase64
          this.stopCamera()
          this.pageState = 'singleConfirm'
        }
      },
      selectPart(index, id) {
        this.activePartIndex = index
        this.active_id = id
      },
      stopCamera() {
        if (this.animationFrameId) {
          cancelAnimationFrame(this.animationFrameId)
          this.animationFrameId = null
        }
        if (this.stream) {
          this.stream.getTracks().forEach(track => track.stop())
          this.stream = null
        }
        if (this.videoElement && document.body.contains(this.videoElement)) {
          document.body.removeChild(this.videoElement)
          this.videoElement = null
        }
        this.showCamera = false
      },
      // ...
      switchCamera() {
        this.pageState = 'switch'
        // 1. 切换摄像头状态
        setTimeout(() => {
          this.pageState = 'camera'
          this.isFrontCamera = !this.isFrontCamera
          this.$nextTick(() => {
            this.initCamera()
          })
        }, 0)
      },
      // ...
      retake() {
        // 此方法现在用于单张照片重拍
        this.pageState = 'camera'
        this.resetWorkflowState()
        this.$nextTick(() => this.initCamera())
      },
      // ... (confirm, checkStatusfn, getResultData, showPoseGuide methods remain the same) ...
      async confirm() {
        uni.showLoading({ title: this.$t('zhen.analyzing_smart') })

        upload({
          url: '/api/hospital/upload', // 你的后端上传路径
          filePath: this.singlePhotoPath,
          name: 'file', // 后端接收字段
          showLoading: false,
          formData: {
            bizType: 'user-avatar' // 业务参数，根据后端需求传
          }
        })
          .then(res => {
            if (res.result && res.result.url) {
              const params = {
                acupoint_id: this.active_id,
                pic_url: res.result.url,
                user_id: this.userInfo.id
              }
              createAcupoint(params).then(res => {
                if (res.result && res.result.appoint_no) {
                  this.appoint_no = res.result.appoint_no
                  this.checkStatusfn()
                } else {
                  uni.hideLoading()
                  uni.showToast({ title: res.message, icon: 'none' })
                }
              })
            } else {
            }
          })
          .catch(err => {
            console.error('上传失败', err)
          })
      },
      async getResultData() {
        const res = await getResult(this.appoint_no)

        try {
          const response = await getResult(this.appoint_no)
          if (response.code === 200 && response.result) {
            const resultsData = response.result
            this.analysisResult = {
              picUrl: resultsData.pic_url,
              acupointList: resultsData.acupointList.map(point => ({
                ...point,
                xaxis: Number(point.x_axis),
                yaxis: Number(point.y_axis)
              })),
              linkTo: {
                shoppingMallAppId: resultsData.shoppingMallAppId,
                shoppingMallUrl: resultsData.shoppingMallUrl
              }
            }
            this.pageState = 'results'
          } else {
            throw new Error(response.message || '分析服务出错，请稍后重试')
          }
        } catch (error) {
          uni.showToast({ title: error.message, icon: 'none' })
        } finally {
          uni.hideLoading()
        }
      },
      async checkStatusfn() {
        this.pollCount = 0
        const loop = async () => {
          try {
            const res = await checkStatus(this.appoint_no)

            if (res.result && res.result.status === '000') {
              clearTimeout(this.pollTimer)
              this.pollTimer = null
              this.getResultData()
              return
            }
            if (res.result && res.result.status === '101') {
              uni.showToast({ title: res.result.msg, icon: 'none' })
              clearTimeout(this.pollTimer)
              this.pollTimer = null
              return
            }

            this.pollCount++
            if (this.pollCount >= this.maxPollCount) {
              uni.showToast({ title: '分析超时，请稍后再试', icon: 'none' })
              return
            }

            this.pollTimer = setTimeout(loop, this.interval)
          } catch (err) {
            console.error('接口异常', err)
            this.pollCount++
            if (this.pollCount >= this.maxPollCount) {
              // TODO
            } else {
              this.pollTimer = setTimeout(loop, this.interval)
            }
          }
        }
        loop()
      },
      showPoseGuide() {
        this.confirm()
        uni.showModal({
          title: '正确姿势指引',
          content: '请将身体部位对准屏幕中央的白色轮廓线，保持光线充足，点击下方圆形按钮进行拍照。',
          showCancel: false
        })
      },
      retakeMultiPhotos() {
        this.pageState = 'camera'
        this.resetWorkflowState()
        this.$nextTick(() => this.initCamera())
      },
      skipOptionalPhotos() {
        if (!this.canSkip) return
        this.capturedPhotos.push({ path: null })
        // Add a null placeholder for the skipped photo

        // Move to the next step
        this.currentStepIndex++

        // Check if the workflow is complete after skipping
        if (this.currentStepIndex >= this.currentWorkflow.steps.length) {
          this.stopCamera()
          this.pageState = 'multiConfirm'
        } else {
          // If not complete, prepare for the next step (e.g., right face)
          uni.showToast({
            title: this.$t('zhen.please_prepare', { label: this.currentStepConfig.label }),
            icon: 'none',
            duration: 1500
          })
        }
      },
      async confirmMultiPhotos() {
        if (this.isPolling) return // 如果正在轮询，防止重复点击
        uni.showLoading({ title: this.$t('zhen.uploading') })

        try {
          const photosToUpload = this.capturedPhotos.filter(p => p.path !== null)
          const uploadPromises = photosToUpload.map(photo => {
            const originalIndex = this.capturedPhotos.findIndex(p => p.path === photo.path)
            const stepLabel = this.currentWorkflow.steps[originalIndex].label
            return upload({
              url: '/api/hospital/upload',
              filePath: photo.path,
              name: 'file',
              showLoading: false,
              formData: { bizType: `${this.cameraSource}-${stepLabel}` }
            })
          })

          const uploadResults = await Promise.all(uploadPromises)
          const photoUrls = uploadResults.map(res => {
            if (res.result && res.result.url) {
              return res.result.url
            }
            throw new Error(this.$t('zhen.photo_upload_fail'))
          })

          uni.hideLoading()
          uni.showLoading({ title: this.$t('zhen.analyzing_smart') })

          let analysisRes = null
          let params = {}

          if (this.cameraSource === 'tongue') {
            params = {
              tongueFrontImg: photoUrls[0],
              tongueBottomImg: photoUrls[1],
              user_id: this.userInfo.id
            }
            this.isPolling = true
            const createRes = await createTonguet(params)
            if (createRes && createRes.code === 200 && createRes.result.appoint_no) {
              this.appoint_no = createRes.result.appoint_no
              this.isPolling = true
              this.startPollingForTongueResult()
            } else {
              uni.showToast({ title: createRes.message, icon: 'none' })
              this.isPolling = false
              throw new Error(createRes.message || this.$t('zhen.create_task_fail'))
            }
          } else if (this.cameraSource === 'face') {
            this.isPolling = true
            params = {
              faceImgPath: photoUrls[0],
              faceLeftImgPath: photoUrls[1],
              faceRightImgPath: photoUrls[2],
              user_id: this.userInfo.id
            }
            const createFaceRes = await createFaceDiagnosis(params)

            if (createFaceRes.code === 200 && createFaceRes.result && createFaceRes.result.subject) {
              this.questionnaireData = {
                faceId: createFaceRes.result.faceId,
                id: createFaceRes.result.id,
                questions: createFaceRes.result.subject
              }
              this.initializeAnswers()
              this.pageState = 'questionnaire'
            } else {
              uni.showToast({ title: createFaceRes.message, icon: 'none' })
              this.isPolling = false
              throw new Error(createFaceRes.message || this.$t('zhen.face_service_error'))
            }
          } else {
            throw new Error(this.$t('zhen.unknown_type', { type: this.cameraSource }))
          }

          if (analysisRes && analysisRes.code === 200 && analysisRes.result) {
            if (this.cameraSource === 'tongue') {
              this.analysisResult = analysisRes.result
              this.analysisResult.userInfo = this.userInfo
            } else if (this.cameraSource === 'face') {
              this.analysisResult = {
                picUrl: analysisRes.result.report_image_url || photoUrls[0]
              }
            }
            this.pageState = 'results'
          }
        } finally {
          uni.hideLoading()
        }
      },
      initializeAnswers() {
        this.answers = this.questionnaireData.questions.reduce((acc, q) => {
          acc[q.subjectId] = null
          return acc
        }, {})
      },
      selectAnswer(questionId, answerCode) {
        if (this.isAnswering) return
        this.answers[questionId] = answerCode
        this.submitSingleAnswer(questionId, answerCode)
      },
      handleAgeInput(questionId) {
        if (this.isAnswering) return
        const age = this.answers[questionId]
        if (!age || age <= 0) {
          uni.showToast({ title: this.$t('zhen.please_input_valid_age'), icon: 'none' })
          return
        }
        this.submitSingleAnswer(questionId, age)
      },
      async submitSingleAnswer(questionId, answerValue) {
        this.isAnswering = true
        uni.showLoading({ title: this.$t('zhen.please_wait'), mask: true })

        try {
          const payload = {
            id: this.questionnaireData.id,
            faceId: this.questionnaireData.faceId,
            answer: [
              {
                subjectId: String(questionId),
                answerCode: String(answerValue)
              }
            ]
          }
          const res = await answerQuestion(payload)
          if (res.code === 200 && res.result) {
            if (res.result.isFinalResult === '1') {
              await this.fetchFinalFaceResult()
            } else if (res.result.subject && res.result.subject.length > 0) {
              this.questionnaireData.questions = res.result.subject
              this.initializeAnswers()
            } else {
              await this.fetchFinalFaceResult()
            }
          } else {
            throw new Error(res.message || this.$t('zhen.submit_answer_fail'))
          }
        } catch (err) {
          uni.showToast({ title: err.message, icon: 'none' })
        } finally {
          this.isAnswering = false
          uni.hideLoading()
        }
      },
      async fetchFinalFaceResult() {
        uni.showLoading({ title: this.$t('zhen.generating_report') })
        try {
          const finalRes = await getFinalFaceResult(this.questionnaireData.faceId)
          if (finalRes.code === 200 && finalRes.result) {
            this.analysisResult = { ...finalRes.result, userInfo: this.userInfo }
            this.pageState = 'results'
          } else {
            throw new Error(finalRes.message || this.$t('zhen.get_report_fail'))
          }
        } catch (err) {
          uni.showToast({ title: err.message, icon: 'none' })
        } finally {
          uni.hideLoading()
        }
      },
      startPollingForTongueResult() {
        this.pollCount = 0
        clearTimeout(this.pollTimer)
        this.isPolling = true
        const loop = async () => {
          try {
            const statusRes = await checkTongueStatus(this.appoint_no)
            if (statusRes.result && statusRes.result.status === '000') {
              clearTimeout(this.pollTimer)
              this.pollTimer = null
              const finalResultRes = await getTongueResult(this.appoint_no)
              if (finalResultRes && finalResultRes.code === 200 && finalResultRes.result) {
                this.analysisResult = finalResultRes.result
                this.analysisResult.userInfo = this.userInfo
                this.pageState = 'results'
                uni.hideLoading()
              } else {
                throw new Error(finalResultRes.message || this.$t('zhen.get_diagnosis_report_fail'))
              }
              this.isPolling = false
              return
            }
            if (statusRes.result && statusRes.result.status === '101') {
              clearTimeout(this.pollTimer)
              uni.hideLoading()
              this.isPolling = false
              uni.showToast({ title: statusRes.result.msg, icon: 'none' })
              return
            }

            this.pollCount++
            if (this.pollCount >= this.maxPollCount) {
              clearTimeout(this.pollTimer)
              this.isPolling = false // [MODIFIED] 成功后重置按钮状态
              uni.showToast({ title: this.$t('zhen.analysis_timeout'), icon: 'none' })
              throw new Error('分析超时，请稍后再试')
            }
            this.pollTimer = setTimeout(loop, this.interval)
          } catch (err) {
            // console.error('轮询过程中发生错误:', err)
            clearTimeout(this.pollTimer)
            this.isPolling = false
            uni.hideLoading()
            uni.showToast({ title: err.message || this.$t('zhen.analysis_error'), icon: 'none' })
          }
        }
        loop()
      },
      restart() {
        this.analysisResult = { picUrl: '', acupointList: [], linkTo: {} }
        this.pageState = 'camera'
        this.resetWorkflowState()
        clearTimeout(this.pollTimer)
        this.pollTimer = null
        this.$nextTick(() => this.initCamera())
      }
    }
  }
</script>

<style lang="scss" scoped>
  .container {
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100vw;
    background-color: #000;
    overflow: hidden;
  }

  /* [MODIFIED] Added padding-bottom to reserve space for the fixed controls */
  .camera-container {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    padding-bottom: 160px; /* This should match the height of .bottom-controls */
    box-sizing: border-box; /* Ensures padding is included in the height calculation */
  }

  .camera-wrapper {
    flex: 1;
    position: relative;
    overflow: hidden;
    background-color: #000;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .camera-canvas,
  .preview-image {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
  }

  .camera-prompt {
    position: absolute;
    top: 20px;
    left: 0;
    right: 0;
    z-index: 5;
    text-align: center;
    pointer-events: none; /* 让下层元素可以被点击 */
  }

  .prompt-text {
    color: #fff;
    padding: 6px 15px;
    font-size: 14px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  }

  .guide-image {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    opacity: 0.8;
  }

  /* [MODIFIED] Changed to position: fixed */
  .bottom-controls {
    position: fixed; /* Changed from 'relative' to 'fixed' */
    bottom: 0;
    left: 0;
    right: 0;

    background-color: rgba(0, 0, 0, 0.5);
    color: #fff;
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    padding-top: 10px;
    z-index: 10;
    height: 160px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
    transition: all 0.2s ease-in-out;
  }

  .part-selector {
    width: 100%;
    margin-bottom: 10px;
    overflow: visible;
  }
  .scroll-view {
    white-space: nowrap;
    width: 100%;
    text-align: center;
  }
  .part-item {
    display: inline-block;
    color: #ccc;
    padding: 8px 15px;
    font-size: 15px;
    transition: all 0.2s ease;
  }
  .part-item.active {
    color: #4cd964;
    font-weight: bold;
    transform: scale(1.15);
  }
  .action-buttons {
    display: flex;
    justify-content: space-around;
    align-items: center;
    width: 100%;
    padding: 5px 0;
    box-sizing: border-box;
  }
  .button-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    color: white;
    flex: 1;
    text-align: center;
    cursor: pointer;
  }
  .icon-placeholder {
    width: 32px;
    height: 32px;
    background-color: rgba(255, 255, 255, 0.2);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    color: #fff;
  }
  .btn-text {
    font-size: 13px;
    margin-top: 5px;
    color: #fff;
  }
  .btn-text.primary {
    color: #4cd964;
    font-weight: bold;
  }
  .shutter-button-wrapper {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background-color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 4px;
    box-sizing: border-box;
    cursor: pointer;
    transition: transform 0.1s ease;
  }
  .shutter-button-wrapper:active {
    transform: scale(0.95);
  }
  .shutter-button-wrapper.disabled {
    opacity: 0.5;
    pointer-events: none;
  }
  .shutter-button {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-color: #fff;
    border: 3px solid #000;
    box-sizing: border-box;
  }
  .confirm-actions {
    display: flex;
    justify-content: space-around;
    align-items: center;
    width: 100%;
    /*
      The height is now controlled by the parent .bottom-controls,
      so min-height might not be strictly necessary but is harmless.
    */
    min-height: 95px;
    padding-bottom: 10px;
  }
  .confirm-actions .button-wrapper .btn-text {
    font-size: 17px;
  }

  .confirm-page-container {
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100vw;
    /* This padding is for the footer inside this specific container */
    padding-bottom: 160rpx;
    background-color: #f7f8fa;
  }

  .confirm-page-header {
    text-align: center;
    padding: 12px 0;
    font-size: 18px;
    font-weight: 500;
    background-color: #fff;
    position: relative;
    border-bottom: 1px solid #ebedf0;
    flex-shrink: 0;
  }

  .confirm-scroll-view {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    box-sizing: border-box;
  }

  .scroll-content-wrapper {
    padding: 16px;
    box-sizing: border-box;
  }
  .photo-item {
    background-color: #fff;
    border-radius: 8px;
    padding: 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  }

  .photo-label {
    font-size: 16px;
    color: #323233;
  }

  .photo-preview {
    width: 80px;
    height: 80px;
    border-radius: 6px;
    background-color: #eee;
  }

  .confirm-page-footer {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    gap: 24rpx;
    padding: 24rpx 30rpx;
    background-color: #fff;
    border-top: 1rpx solid #f0f0f0;
    padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
    padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
    z-index: 100;
  }
  .footer-btn {
    flex: 1;
    height: 44px;
    line-height: 44px;
    border-radius: 22px;
    font-size: 16px;
    margin: 0;
  }
  .retake-btn {
    background-color: #f2f3f5;
    color: #323233;
    border: 1px solid #ebedf0;
  }
  .confirm-btn {
    background-color: #007aff;
    color: #fff;
  }

  .questionnaire-page {
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100vw;
    background-color: #afa0ec;
    padding: 30rpx;
    box-sizing: border-box;
  }

  .questionnaire-header {
    padding: 20rpx 0 40rpx;
    color: #fff;
    text-align: left;
    .header-text {
      font-size: 32rpx;
      line-height: 1.5;
    }
  }

  .questionnaire-scroll {
    flex: 1;
    height: 0;
  }

  .question-list.answering {
    pointer-events: none;
    opacity: 0.7;
  }

  .question-card {
    background-color: #fff;
    border-radius: 20rpx;
    padding: 40rpx 30rpx;
    margin-bottom: 30rpx;
  }

  .question-title-wrapper {
    display: flex;
    align-items: center;
    margin-bottom: 40rpx;
    .question-title {
      font-size: 34rpx;
      font-weight: 600;
      color: #333;
    }
  }

  .answer-options {
    display: flex;
    flex-direction: column;
    gap: 30rpx;
  }

  .age-input {
    width: 100%;
    height: 90rpx;
    line-height: 90rpx;
    text-align: center;
    background-color: #fff;
    border: 1px solid #e0e0e0;
    border-radius: 45rpx;
    font-size: 32rpx;
    color: #333;
    box-sizing: border-box;
  }

  .answer-btn {
    width: 100%;
    height: 90rpx;
    line-height: 90rpx;
    text-align: center;
    background-color: #fff;
    color: #333;
    border: 1px solid #e0e0e0;
    border-radius: 45rpx;
    font-size: 32rpx;
    transition: all 0.2s;

    &.active {
      background-color: #8c6df6;
      color: #fff;
      border-color: #8c6df6;
      font-weight: 500;
    }
  }
  .skip-prompt-box {
    position: absolute;
    bottom: 60px;
    left: 10%;
    right: 10%;
    background-color: rgba(40, 40, 40, 0.7);
    color: #ffffff;
    padding: 8px 16px;
    border-radius: 20px;
    font-size: 14px;
    z-index: 6;
    text-align: center;
    white-space: nowrap;
    cursor: pointer;

    .skip-highlight {
      color: #ffd966;
    }
  }
</style>
